package com.xtsoft.platform.report.controller;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.xtsoft.core.controller.GenericController;
import com.xtsoft.core.repository.QueryFilter;
import com.xtsoft.core.repository.QueryResult;
import com.xtsoft.core.utils.BeanUtil;
import com.xtsoft.core.utils.ResultMsg;
import com.xtsoft.core.utils.StringUtils;
import com.xtsoft.core.utils.UUIDGenerator;

import com.xtsoft.platform.base.system.domain.SysResource;
import com.xtsoft.platform.base.system.domain.SysUser;
import com.xtsoft.platform.base.system.service.SysResourceService;
import com.xtsoft.platform.globe.enums.YesNo;
import com.xtsoft.platform.globe.utils.SecurityUtils;
import com.xtsoft.platform.report.domain.RepDefine;
import com.xtsoft.platform.report.service.RepDefineService;
import com.xtsoft.platform.report.utils.SerialNumUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.ParseException;
import java.util.Date;
//撤销方便寻找
 /**
 * 
 * @ClassName:  RepDefine   
 * <p> 报表处理类 </p>
 * @author: Codegen-代码生成器
 * @date:   2019年12月3日 上午10:59:46
 */
 @Tag(name = "报表--处理接口")   
@RestController
public class RepDefineController extends GenericController{
	
	private final Logger log = LoggerFactory.getLogger(RepDefineController.class);
	
	@Autowired	
	private RepDefineService repDefineService;
	
	@Autowired
	private SysResourceService sysResourceService;
	
	
    /**
     *  <p>新增一个报表</p>  
//     * @param repDefine 要新增的报表
     * @return ResponseEntity<ResultMsg>, ResultMsg的Data中包含 报表
     * @throws URISyntaxException 如果URI语法不正确，则抛URI语法异常                     
	 * @author Codegen-代码生成器
     * @throws IOException 
	 * @date 2021-10-28 12:57:33
    */
	@PostMapping("/repDefine/add")
	@Parameter(name = "repDefine", description = "要新增的", required = false)
	@Operation(summary ="新增，根据前台传递的报表新增")
    public ResponseEntity<ResultMsg> add(
    		@RequestParam(value = "filePath", required = false) MultipartFile filePath,
    		@RequestParam(value = "fileName", required = false) String fileName,
    		@RequestParam(value = "descript", required = false) String descript,
    		@RequestParam(value = "dbVersion", required = false) String dbVersion,
    		@RequestParam(value = "dbType", required = false) int dbType,
    		@RequestParam(value = "dbchName", required = false) String dbchName,
    		@RequestParam(value = "dbName", required = false) String dbName,
    		@RequestParam(value = "reportName", required = false) String reportName,
    		@RequestParam(value = "repDefineId", required = false) String repDefineId
    		) throws URISyntaxException, IOException {
    	RepDefine repDefine = repDefineService.get(repDefineId);
    	ResultMsg resultMsg = new ResultMsg();
		SysUser user = (SysUser) SecurityUtils.getLoginedUser();
    	if(repDefine == null) {
    		//新增

    		 repDefine = new RepDefine();
    		 repDefine.setCreateDate(new Date());
    		 repDefine.setState(YesNo.No.getIntValue());
    	     repDefine.setCreateUserId(user.getUserId());
    	     repDefine.setIsMenu(YesNo.No.getIntValue());
    	     RepDefine define = repDefineService.orderByobjCode();
 	        if(StringUtils.isEmpty(define)){
	        	repDefine.setObjCode("D0001");
	        }else{
	        	repDefine.setObjCode(SerialNumUtil.generaterNextNumber(define.getObjCode(), "D", 5));
	        }
 	       resultMsg.setMsg("新增成功！");
    	}else {
    		//修改
    		repDefine.setEditDate(new Date());
            repDefine.setEditUserId(user.getUserId());
            resultMsg.setMsg("编辑成功！");
    	}

        if(filePath != null && !StringUtils.isBlank(filePath.getOriginalFilename())) {
        	//如果是修改
        	if(!StringUtils.isBlank(repDefine.getRepDefineId())) {
	        	String path=request.getSession().getServletContext().getRealPath("/") + repDefine.getFilePath();
				File filed = new File(path);
				if (filed.exists()){
					filed.delete();
				}
				path = path.substring(0, path.lastIndexOf("/"));
				filed = new File(path);
				if (filed.exists()){
					filed.delete();
				}
        	}
        	byte[] bytes = filePath.getBytes();
   	    	String uuid= UUIDGenerator.getUUID();
   	    	String uploadFileName=filePath.getOriginalFilename().replace("\"", "“");
   	    	String format = uploadFileName.substring(uploadFileName.lastIndexOf("."));
   	    	String fileNames = UUIDGenerator.getUUID()+format;
   	    	String path=request.getSession().getServletContext().getRealPath("/")+"/upload/"+uuid;//绝对路径
   	    	String absolutePath="/upload/"+uuid+"/" +fileNames;//相对路径
   	    	Path dirpath = Paths.get(path);//文件夹路径
   	    	Path filepath = Paths.get(dirpath+"/"+fileNames);//文件路径
   	    	Files.createDirectories(dirpath);//创建文件夹
   	        Files.write(filepath, bytes);//创建文件
   	        repDefine.setFilePath(absolutePath);
   	        repDefine.setFileName(fileNames);
        }
    	repDefine.setDescript(descript);
    	repDefine.setDbType(dbType);
    	repDefine.setDbchName(dbchName);
    	repDefine.setDbName(dbName);
    	repDefine.setReportName(reportName);
    	repDefine.setDbVersion(dbVersion);
    	repDefine.setUpdateDate(new Date().getTime());
    	
        RepDefine result = repDefineService.save(repDefine);
        resultMsg.setSuccess(true);
        resultMsg.setData(result);
        return new ResponseEntity<ResultMsg>(resultMsg,HttpStatus.OK);
    }	

    /**
     * <p>更新一个报表</p>    
     * @param repDefine 要更新的报表
     * @return ResponseEntity<ResultMsg>, json格式
     * @throws URISyntaxException 如果URI语法不正确，则抛URI语法异常
	 * @author Codegen-代码生成器
	 * @date 2021-10-28 12:57:33
     */
    @PostMapping("/repDefine/update")
	@Parameter(name = "repDefine", description = "要更新的报表", required = false)
	@Operation(summary ="更新，根据传递的 报表更新实体")
    public ResponseEntity<ResultMsg> update(@RequestBody RepDefine repDefine) throws URISyntaxException, IllegalAccessException, InvocationTargetException {
		if(null == repDefine){
			return new ResponseEntity<ResultMsg>(new ResultMsg(false,"更新失败，提交的记录为空"),HttpStatus.OK); 
		}
		SysUser user = (SysUser) SecurityUtils.getLoginedUser();
		log.info("单条更新报表开始......", user.getLoginId(), user.getUsername(), getClientIp());
		//若 报表无主键值，说明调用错误
        if (StringUtils.isBlank(repDefine.getRepDefineId())) {
			log.info("单条更新报表失败，报表对象RepDefineId无属性值", user.getLoginId(), user.getUsername(), getClientIp());
			return new ResponseEntity<ResultMsg>(new ResultMsg(false,"更新失败，更新的记录无唯一标识值"),HttpStatus.OK);
        }
        //若类存在存在关联关系，前台传递过来的关联属性大概率为空，执行以下处理
		RepDefine result = repDefineService.get(repDefine.getRepDefineId());
		BeanUtil.copyNotNullProperties(result, repDefine);
		result = repDefineService.save(result);
		log.info("单条更新报表成功", user.getLoginId(), user.getUsername(), getClientIp());
        return new ResponseEntity<ResultMsg>(new ResultMsg(true,"更新成功",result),HttpStatus.OK);
    }  

    /**
	 *   <p>查询报表列表，若分页，则页码信息在Request的参数中，包括当前页，每页记录数</p>
     * @return ResponseEntity<ResultMsg>，json格式
     * @throws URISyntaxException 如果出错，则产生页码信息的 HTTP headers
	 * @author Codegen-代码生成器
	 * @date 2021-10-28 12:57:33
     */
    @GetMapping("/repDefine/getAll")
	@Operation(summary ="查询，根据传递的条件查询报表列表，条件参数在Request中")
    public ResponseEntity<QueryResult<RepDefine>> getAll()
        throws URISyntaxException, JsonParseException, JsonMappingException, IOException, ParseException {
		SysUser user = (SysUser) SecurityUtils.getLoginedUser();
		log.info("获取报表列表开始......", user.getLoginId(), user.getUsername(), getClientIp());
        QueryFilter<RepDefine> filter=new QueryFilter<RepDefine>(RepDefine.class);
        filter.addFilterFromRequest(request);
        QueryResult<RepDefine> result= repDefineService.anyQuery(filter);
		log.info("获取报表列表成功", user.getLoginId(), user.getUsername(), getClientIp());
        return new ResponseEntity<QueryResult<RepDefine>>(result,HttpStatus.OK);
    }

    /**
	 *   <p>根据报表唯一ID值获取报表</p>
     * @param id 报表唯一ID值
     * @return  ResponseEntity<RepDefine>
	 * @author Codegen-代码生成器
	 * @date 2021-10-28 12:57:33		
     */
    @GetMapping("/repDefine/get/{id}")
	@Parameter(name = "id", description = "对象唯一Id", required = false)
	@Operation(summary ="获取单个报表，若根据报表唯一Id获取到了多个对象则发生异常")
    public ResponseEntity<ResultMsg> get(@PathVariable String id) {
		if(StringUtils.isBlank(id)){
			 return new ResponseEntity<ResultMsg>(new ResultMsg(false,"获取单条记录失败，未给定记录的唯一标识"),HttpStatus.OK);
		}
		SysUser user = (SysUser) SecurityUtils.getLoginedUser();
		log.info("获取报表开始......", user.getLoginId(), user.getUsername(), getClientIp());
        RepDefine repDefine = repDefineService.get(id);
		/*
		*  <p> ofNullable执行逻辑：如果对象为空，则执行orElse，否则执行.map...
		*		return Optional.ofNullable(sysRole).map(result -> new ResponseEntity<>(result, HttpStatus.OK))
		*		.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));		
		*/
		
		if( null == repDefine ){
			log.info("获取报表失败", user.getLoginId(), user.getUsername(), getClientIp());
			return new ResponseEntity<ResultMsg>(new ResultMsg(false,"获取单条记录失败，提交的记录可能被删除或不存在"),HttpStatus.OK);
		}
		log.info("获取报表成功", user.getLoginId(), user.getUsername(), getClientIp());
		return new ResponseEntity<ResultMsg>(new ResultMsg(true,"获取成功",repDefine),HttpStatus.OK);
    } 

    /**
     *     <p>根据报表唯一ID值删除单个报表</p>
     * @param  id 报表唯一ID值
     * @return ResponseEntity,json格式
	 * @author Codegen-代码生成器
	 * @date 2021-10-28 12:57:33		 
     */
    @GetMapping("/repDefine/delete/{id}")
	@Parameter(name = "id", description = "报表唯一Id", required = false)
	@Operation(summary ="删除单个报表")
    public ResponseEntity<ResultMsg> delete(@PathVariable String id) {
		if(StringUtils.isBlank(id)){
			 return new ResponseEntity<ResultMsg>(new ResultMsg(false,"删除单条记录失败，未给定记录的唯一标识"),HttpStatus.OK);
		}
		SysUser user = (SysUser) SecurityUtils.getLoginedUser();
		log.info("删除单条报表开始......", user.getLoginId(), user.getUsername(), getClientIp());
		//如果当前报表已经发布则不允许删除
		RepDefine repDefine = repDefineService.get(id);
		if(repDefine.getState() == YesNo.Yes.getIntValue()) {
			 return new ResponseEntity<ResultMsg>(new ResultMsg(false,"当前报表已发布，禁止删除！"),HttpStatus.OK);
		}
		repDefineService.remove(id);
		log.info("删除单条报表成功", user.getLoginId(), user.getUsername(), getClientIp());
        return new ResponseEntity<ResultMsg>(new ResultMsg(true,"删除成功"),HttpStatus.OK);
    }
	
    /**
     *     <p>根据报表唯一ID值集合，批量删除报表</p>
     * @param  ids 报表唯一ID值集合
     * @return ResponseEntity<ResultMsg>,返回结果中有删除的记录数，json格式
	 * @author Codegen-代码生成器
	 * @date 2021-10-28 12:57:33		 
     */
    @PostMapping("/repDefine/deleteBatch")
	@Parameter(name = "ids", description = "逗号分隔的报表Id集合", required = false)
	@Operation(summary ="删除报表集合")
    public ResponseEntity<ResultMsg> deleteBatch(@RequestParam String ids) {
		if(StringUtils.isBlank(ids)){
			 return new ResponseEntity<ResultMsg>(new ResultMsg(false,"批量删除记录失败，未给定记录的唯一标识集合"),HttpStatus.OK);
		}
		SysUser user = (SysUser) SecurityUtils.getLoginedUser();
		log.info("批量删除报表开始......", user.getLoginId(), user.getUsername(), getClientIp());
        long rows = repDefineService.deleteBatch(ids);
		log.info("批量删除报表成功", user.getLoginId(), user.getUsername(), getClientIp());
        return new ResponseEntity<ResultMsg>(new ResultMsg(true,"批量删除记录成功",rows),HttpStatus.OK);
    }
	
    /**
     *     <p>根据报表唯一ID值集合，批量更新报表</p>
     * @param  ids 报表唯一ID值集合
	 * @param  properityName 报表要更新的属性名，不带类名
	 * @param  properityValue 报表要更新的属性值
     * @return ResponseEntity<ResultMessage>,返回结果中有更新的记录数，json格式
	 * @author Codegen-代码生成器
	 * @date 2021-10-28 12:57:33		 
     */
    @PostMapping("/repDefine/updateBatch")
	@Parameters({@Parameter( name = "properityName", description = "要更新的属性名不带类名，只能是类单个属性名且不能是集合类型", required = false),
			@Parameter(name = "properityValue", description="属性值", required = false),
			@Parameter(name = "ids", description="逗号分隔的企业类型Id集合", required = false)
	})
	@Operation(summary ="更新报表集合")
    public ResponseEntity<ResultMsg> updateBatch(@RequestParam String properityName,
		@RequestParam String properityValue,
		@RequestParam String ids) {
		if(StringUtils.isBlank(ids) || StringUtils.isBlank(properityValue) || StringUtils.isBlank(properityName)){
			 return new ResponseEntity<ResultMsg>(new ResultMsg(false,"批量更新记录失败，未给定记录的唯一标识集合，或未给定属性名、或属性值"),HttpStatus.OK);
		}
		SysUser user = (SysUser) SecurityUtils.getLoginedUser();
		log.info("批量更新报表开始......", user.getLoginId(), user.getUsername(), getClientIp());
        long rows = repDefineService.updateBatch(properityName,properityValue,ids);
		log.info("批量更新报表成功", user.getLoginId(), user.getUsername(), getClientIp());
        return new ResponseEntity<ResultMsg>(new ResultMsg(true,"批量更新记录成功",rows),HttpStatus.OK);
    }	
    
    
    /**
     * 
     * <p> 发布报表  </p>  
     * @param repDefineId
     * @return
     * @return ResponseEntity<ResultMsg>
     * @throws  
     * @author litao
     * @date 2021年10月28日 
     * @time 下午3:42:33
     */
	@PostMapping("/repDefine/publish")
	@Parameters({@Parameter( name = "repDefineId", required = false),
			@Parameter(name = "preResourceId", required = false),
			@Parameter(name = "resourceName", required = false),
			@Parameter(name = "descript",required = false)
	})
	@Operation(summary ="发布报表")
	public ResponseEntity<ResultMsg> publish(
			@RequestParam(value = "repDefineId", required = false) String repDefineId,
			@RequestParam(value = "preResourceId", required = false) String preResourceId,
			@RequestParam(value = "resourceName", required = false) String resourceName,
			@RequestParam(value = "resourceId", required = false) String resourceId,
			@RequestParam(value = "descript", required = false) String descript
			){
		if(StringUtils.isBlank(repDefineId)) {
			return new ResponseEntity<ResultMsg>(new ResultMsg(false, "发布失败！该报表ID为空！"),HttpStatus.OK);
		}
		RepDefine repDefine = repDefineService.get(repDefineId);
		if(repDefine == null) {
			return new ResponseEntity<ResultMsg>(new ResultMsg(false, "发布失败！该报表不存在！"),HttpStatus.OK);
		}
		repDefine.setState(YesNo.Yes.getIntValue());
		ResultMsg reusltMsg = repDefineService.savePublish(repDefine,preResourceId,resourceName,resourceId,descript);
		return new ResponseEntity<ResultMsg>(reusltMsg,HttpStatus.OK);
	}
	
	/**
	 * 
	 * <p> 撤销报表  </p>  
	 * @param repDefineId
	 * @return
	 * @return ResponseEntity<ResultMsg>
	 * @throws  
	 * @author litao
	 * @date 2021年10月28日 
	 * @time 下午3:44:16
	 */
	@GetMapping("/repDefine/revocation/{repDefineId}")
	@Parameter(name = "repDefineId", description = "对象唯一Id", required = false)
	@Operation(summary ="撤销报表")
	public ResponseEntity<ResultMsg> revocation(@PathVariable String repDefineId){
		if(StringUtils.isBlank(repDefineId)) {
			return new ResponseEntity<ResultMsg>(new ResultMsg(false, "撤销失败！该报表ID为空！"),HttpStatus.OK);
		}
		RepDefine repDefine = repDefineService.get(repDefineId);
		
		if(repDefine == null) {
			return new ResponseEntity<ResultMsg>(new ResultMsg(false, "撤销失败！该报表不存在！"),HttpStatus.OK);
		}
		//判断当前报表是否分配了角色
		if(!StringUtils.isBlank(repDefine.getResourceId())) {
			String resourceId = repDefine.getResourceId();
			SysResource sysResource = sysResourceService.getByResourceId(resourceId);
			if(!StringUtils.isEmpty(sysResource)) {
				return new ResponseEntity<ResultMsg>(new ResultMsg(false, "撤销失败！该报表已分配角色！"),HttpStatus.OK);
			}
		}
		repDefine.setState(YesNo.No.getIntValue());
		repDefineService.save(repDefine);
		return new ResponseEntity<ResultMsg>(new ResultMsg(true, "撤销成功！"),HttpStatus.OK);
	}
	
}
